package com.acdc.wechat.service;

import com.acdc.wechat.config.WechatPayConfig;
import com.acdc.wechat.utils.WechatPayDecryptUtil;
import com.acdc.wechat.utils.WechatPayV3SignatureVerifier;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.service.ISysUserService;

import java.nio.charset.StandardCharsets;


import java.util.HashMap;
import java.util.Map;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.util.List;
import com.acdc.business.domain.RechargeRecord;
import com.acdc.business.domain.RefundRecord;
import com.acdc.business.service.IRechargeRecordService;
import com.acdc.business.service.IRefundRecordService;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.math.BigDecimal;

@Slf4j
@Service
public class WechatRefundService {

    private final ObjectMapper objectMapper = new ObjectMapper();
    
    @Autowired
    private WechatPayConfig wechatPayConfig;
    
    @Value("${wechat.pay.refund-notify-url}")
    private String refundNotifyUrl;
    
    @Value("${wechat.pay.merchant-serial-no}")
    private String merchantSerialNo;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IRechargeRecordService rechargeRecordService;

    @Autowired
    private IRefundRecordService refundRecordService;

    /**
     * 申请退款
     */
    public Map<String, Object> createRefund(String outTradeNo,  int refundAmount) throws Exception {
        // 根据outTradeNo获取充值订单信息
        RechargeRecord query = new RechargeRecord();
        query.setOrderId(outTradeNo);
        List<RechargeRecord> rechargeRecordList = rechargeRecordService.selectRechargeRecordList(query);
        if (rechargeRecordList.size() > 0) {
            RechargeRecord rechargeRecord = rechargeRecordList.get(0);
            SysUser user = userService.selectUserById(rechargeRecord.getUserId());
            // 生成退款订单号, yyyyMMddHHmmss+userId+随机数
            String outRefundNo = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + user.getUserId() + UUID.randomUUID().toString().substring(0, 4);
            String reason = user.getUserName() + "退款" + refundAmount/100.0f + "元（充值" + rechargeRecord.getAmount() + "元）";
            int totalAmount = (int) (rechargeRecord.getAmount() * 100);
            // 构建请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("out_trade_no", outTradeNo);
            params.put("out_refund_no", outRefundNo);
            params.put("reason", reason);
            
            Map<String, Object> amount = new HashMap<>();
            amount.put("total", totalAmount); // 原订单总金额，单位：分
            amount.put("refund", refundAmount); // 退款金额，单位：分
            amount.put("currency", "CNY");
            params.put("amount", amount);
            
            params.put("notify_url", refundNotifyUrl);
            
            // 创建HTTP请求
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
            httpPost.addHeader("Content-Type", "application/json");
            httpPost.addHeader("Accept", "application/json");
            
            // 生成请求体
            String requestBody = objectMapper.writeValueAsString(params);
            httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
            
            // 执行请求
            try (CloseableHttpResponse response = wechatPayConfig.wechatPayClient().execute(httpPost)) {
                String bodyAsString = EntityUtils.toString(response.getEntity());
                log.info("退款返回数据: {}", bodyAsString);
                
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    throw new RuntimeException("退款失败，HTTP状态码: " + statusCode + ", 响应: " + bodyAsString);
                }
                
                @SuppressWarnings("unchecked")
                Map<String, Object> resultMap = objectMapper.readValue(bodyAsString, Map.class);
                if (resultMap.get("refund_id") == null) {
                    throw new RuntimeException("退款失败: " + resultMap.get("message"));
                }
                // 添加退款记录
                RefundRecord refundRecord = new RefundRecord();
                refundRecord.setOrderId(outTradeNo);
                refundRecord.setRefundOrderId(outRefundNo);
                refundRecord.setAmount(refundAmount/100.0f);
                refundRecord.setStatus(0L);
                refundRecord.setRefundType(0L);
                refundRecord.setCreatedAt(new Date());
                refundRecord.setUpdatedAt(new Date());
                refundRecord.setUserId(user.getUserId());
                refundRecordService.insertRefundRecord(refundRecord);
                return resultMap;
            } catch (Exception e) {
                log.error("退款失败", e);
                throw new RuntimeException("退款失败: " + e.getMessage());
            }
        } else {
            throw new RuntimeException("充值订单不存在");
        }
        
    }
    
    /**
     * 处理退款结果通知
     */
    public String handleRefundNotify(String notifyData, String nonce, String timestamp, String signature) throws Exception {
        log.info("收到退款通知 - nonce: {}, timestamp: {}, signature: {}", nonce, timestamp, signature);
        log.info("通知数据: {}", notifyData);
        
        try {
            // 验证签名 - 使用微信支付V3通知签名验证
            String method = "POST";
            String urlPath = "/wechat/pay/refund-notify";
            String nonceStr = nonce;
            String body = notifyData;
            
            // 使用专门的V3签名验证工具
            boolean verifyResult = WechatPayV3SignatureVerifier.verify(method, urlPath, timestamp, nonceStr, body, signature);
            if (!verifyResult) {
                log.error("退款通知签名验证失败 - 签名不匹配");
                
                // 尝试使用简化验证
                log.info("尝试使用简化签名验证");
                boolean simpleVerifyResult = WechatPayV3SignatureVerifier.verifySimple(method, urlPath, timestamp, nonceStr, body, signature);
                
                if (!simpleVerifyResult) {
                    log.error("简化签名验证也失败");
                    throw new RuntimeException("签名验证失败");
                } else {
                    log.warn("简化签名验证通过，但建议配置完整的证书验证");
                }
            } else {
                log.info("退款通知签名验证成功");
            }
            
        } catch (Exception e) {
            log.error("退款通知签名验证异常", e);
            throw new RuntimeException("签名验证失败: " + e.getMessage());
        }
        
        // 解析通知数据
        @SuppressWarnings("unchecked")
        Map<String, Object> resultMap = objectMapper.readValue(notifyData, Map.class);
        
        // 获取加密的资源数据
        @SuppressWarnings("unchecked")
        Map<String, Object> resource = (Map<String, Object>) resultMap.get("resource");
        
        if (resource == null) {
            log.error("退款通知数据中缺少resource字段");
            throw new RuntimeException("通知数据格式错误：缺少resource字段");
        }
        
        String ciphertext = (String) resource.get("ciphertext");
        String associatedData = (String) resource.get("associated_data");
        String nonceStr = (String) resource.get("nonce");
        
        // 验证解密参数
        if (ciphertext == null || ciphertext.trim().isEmpty()) {
            log.error("ciphertext为空或null");
            throw new RuntimeException("解密参数错误：ciphertext为空");
        }
        
        if (nonceStr == null || nonceStr.trim().isEmpty()) {
            log.error("nonce为空或null");
            throw new RuntimeException("解密参数错误：nonce为空");
        }
        
        // associated_data可以为空，但需要处理
        if (associatedData == null) {
            associatedData = "";
        }
        
        log.info("加密数据 - ciphertext长度: {}, associatedData: '{}', nonce: '{}'", 
                ciphertext.length(), associatedData, nonceStr);
        
        // 解密通知数据
        String decryptData;
        try {
            // 使用专门的解密工具
            decryptData = WechatPayDecryptUtil.decryptWithFallback(ciphertext, associatedData, nonceStr, wechatPayConfig.getApiV3Key());
            log.info("解密成功，解密后数据: {}", decryptData);
            
        } catch (Exception e) {
            log.error("解密失败 - ciphertext: {}, associatedData: '{}', nonce: '{}', apiV3Key长度: {}", 
                    ciphertext, associatedData, nonceStr, wechatPayConfig.getApiV3Key().length());
            log.error("解密异常详情", e);
            throw new RuntimeException("解密通知数据失败: " + e.getMessage());
        }
        
        // 解析解密后的数据
        @SuppressWarnings("unchecked")
        Map<String, Object> refund = objectMapper.readValue(decryptData, Map.class);
        
        // 处理退款结果逻辑（更新订单退款状态等）
        String outRefundNo = (String) refund.get("out_refund_no");
        String refundId = (String) refund.get("refund_id");
        String refundStatus = (String) refund.get("refund_status");
        
        // 获取退款金额，从amount中获取refund字段
        Object refundFeeObj = refund.get("amount");
        if (refundFeeObj instanceof Map) {
            Map<String, Object> amountMap = (Map<String, Object>) refundFeeObj;
            refundFeeObj = amountMap.get("refund");
        }
        float refundFee = 0.0f;
        if (refundFeeObj instanceof Number) {
            refundFee = ((Number) refundFeeObj).intValue() / 100.0f;
        } else if (refundFeeObj instanceof String) {
            refundFee = Float.parseFloat((String) refundFeeObj) / 100.0f;
        }
        
        // 获取原订单号
        String outTradeNo = (String) refund.get("out_trade_no");
        
        log.info("退款信息 - outRefundNo: {}, refundId: {}, refundStatus: {}, refundFee: {}, outTradeNo: {}", 
                outRefundNo, refundId, refundStatus, refundFee, outTradeNo);
        
        if ("SUCCESS".equals(refundStatus)) {
            // 更新退款记录
            RefundRecord query = new RefundRecord();
            query.setRefundOrderId(outRefundNo);
            List<RefundRecord> refundRecordList = refundRecordService.selectRefundRecordList(query);
            if (refundRecordList.size() > 0) {
                RefundRecord refundRecord = refundRecordList.get(0);
                if (refundRecord.getStatus() == 1L) {
                    return "{\"code\":\"SUCCESS\",\"message\":\"退款已处理\"}";
                }
                refundRecord.setStatus(1L);
                refundRecord.setUpdatedAt(new Date());
                refundRecord.setTransactionId(refundId);
                refundRecord.setAmount(refundFee);
                refundRecord.setRemark("微信退款成功，退款金额：" + refundRecord.getAmount() + "元");
                refundRecordService.updateRefundRecord(refundRecord);
                // 更新用户余额
                SysUser user = userService.selectUserById(refundRecord.getUserId());
                if (user.getBalance() >= refundRecord.getAmount()) {
                    // 使用BigDecimal计算
                    BigDecimal balance = new BigDecimal(user.getBalance());
                    BigDecimal refundAmount = new BigDecimal(refundRecord.getAmount());
                    balance = balance.subtract(refundAmount);
                    user.setBalance(balance.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue());
                } else {
                    user.setBalance(0.0f);
                }
                userService.updateUser(user);
                log.info("退款成功 - 退款单号: {}, 用户: {}, 金额: {}", 
                        outRefundNo, user.getUserId(), refundRecord.getAmount());
                RechargeRecord rechargeRecord = rechargeRecordService.selectRechargeRecordByOrderId(outTradeNo);
                rechargeRecord.setStatus(2L);
                rechargeRecord.setUpdatedAt(new Date());
                rechargeRecordService.updateRechargeRecord(rechargeRecord);
            }
        } else {
            // 更新退款记录
            RefundRecord query = new RefundRecord();
            query.setRefundOrderId(outRefundNo);
            List<RefundRecord> refundRecordList = refundRecordService.selectRefundRecordList(query);
            if (refundRecordList.size() > 0) {
                RefundRecord refundRecord = refundRecordList.get(0);
                refundRecord.setStatus(2L);
                refundRecord.setUpdatedAt(new Date());
                // 从微信获取失败原因
                String failReason = (String) refund.get("fail_reason");
                if (failReason != null) {
                    refundRecord.setReason(failReason);
                } else {
                    refundRecord.setReason("微信退款失败");
                }
                refundRecordService.updateRefundRecord(refundRecord);
                
                log.info("退款失败 - 退款单号: {}, 原因: {}", outRefundNo, failReason);
            }
        }
        
        // 返回成功响应
        return "{\"code\":\"SUCCESS\",\"message\":\"成功\"}";
    }
    
    /**
     * 查询退款
     */
    public Map<String, Object> queryRefund(String outRefundNo) throws Exception {
        // 创建HTTP请求
        org.apache.http.client.methods.HttpGet httpGet = new org.apache.http.client.methods.HttpGet("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/" + outRefundNo);
        httpGet.addHeader("Accept", "application/json");
        
        // 执行请求
        try (CloseableHttpResponse response = wechatPayConfig.wechatPayClient().execute(httpGet)) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            @SuppressWarnings("unchecked")
            Map<String, Object> result = objectMapper.readValue(bodyAsString, Map.class);
            return result;
        }
    }
    

    

}

